package com.example.canal;
 
import com.alibaba.otter.canal.protocol.CanalEntry;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.domain.po.SystemParameterConfig;
import com.example.service.LeoTest1Service;
import com.example.service.SystemParameterConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
 
/**
 * @Description: 获取到数据后进行相应的处理
 * @Author: leo
 * @Date: 2024/12/5
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AbstractEntryHandler {

    private final SystemParameterConfigService systemParameterConfigService;

    private final LeoTest1Service leoTest1Service;

    public final void handler(CanalEntry.Entry entry) {
 
        CanalEntry.RowChange rowChage = null;
        try {
            rowChage = CanalEntry.RowChange.parseFrom(entry.getStoreValue());
        } catch (Exception e) {
            throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(), e);
        }
 
        CanalEntry.EventType eventType = rowChage.getEventType();
 
        boolean isDdl = rowChage.getIsDdl();
        String schemaName = entry.getHeader().getSchemaName();
        String tableName = entry.getHeader().getTableName();

        // 如果是DDL语句，直接返回
        if (isDdl) {
            log.info("----------DDL语句:[{}]--------", rowChage.getSql());
            return;
        }

        // 查询出系统参数配置表
        QueryWrapper<SystemParameterConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SystemParameterConfig::getParentId, 0)
                .eq(SystemParameterConfig::getParameterKey, "sync_source")
                .eq(SystemParameterConfig::getParameterValue, schemaName)
                .eq(SystemParameterConfig::getDataStatus, 1)
                .last(" limit 1");
        SystemParameterConfig parentConfig = systemParameterConfigService.getOne(queryWrapper);
        if (null == parentConfig){
            log.info("----------系统参数配置表为空--------");
            return;
        }

        QueryWrapper<SystemParameterConfig> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().eq(SystemParameterConfig::getDataStatus, 1)
                .eq(SystemParameterConfig::getParentId, parentConfig.getId())
                .eq(SystemParameterConfig::getParameterKey, "sync_table")
                .eq(SystemParameterConfig::getParameterValue, tableName)
                .last(" limit 1");
        SystemParameterConfig systemParameterConfig = systemParameterConfigService.getOne(queryWrapper2);
        if (null == systemParameterConfig){
            log.info("----------表名:[{}]无需同步--------", tableName);
            return;
        }

        log.info("----------库名:[{}]--------表名:[{}]--------", schemaName, tableName);
        String operation = null;
        List<Map<String, String>> mapList = new ArrayList<>();

        List<CanalEntry.RowData> rowDatasList = rowChage.getRowDatasList();
        switch (eventType) {
            case INSERT:
                for (CanalEntry.RowData rowData : rowDatasList) {
                    Map<String, String> map = new HashMap<>();
                    List<CanalEntry.Column> columns = rowData.getAfterColumnsList();
                    for (CanalEntry.Column column : columns) {
//                        map.put(camelName(column.getName()), column.getValue());

                        map.put(column.getName(), column.getValue());
                    }
                    mapList.add(map);
                }
                operation = "添加";
                break;
            case UPDATE:
                for (CanalEntry.RowData rowData : rowDatasList) {
                    Map<String, String> map = new HashMap<>();
                    List<CanalEntry.Column> columns = rowData.getAfterColumnsList();
                    for (CanalEntry.Column column : columns) {
//                        map.put(camelName(column.getName()), column.getValue());

                        map.put(column.getName(), column.getValue());
                    }
                    Map<String, String> map1 = new HashMap<>();
                    List<CanalEntry.Column> columns1 = rowData.getBeforeColumnsList();
                    for (CanalEntry.Column column : columns1) {
//                        map1.put(camelName(column.getName()), column.getValue());

                        map1.put(column.getName(), column.getValue());
                    }
                    log.info("---------更新之前map=[{}]----------", map1);
                    mapList.add(map);
                }
                operation = "更新";
                break;
            case DELETE:
                for (CanalEntry.RowData rowData : rowDatasList) {
                    Map<String, String> map = new HashMap<>();
                    List<CanalEntry.Column> columns = rowData.getBeforeColumnsList();
                    for (CanalEntry.Column column : columns) {
//                        map.put(camelName(column.getName()), column.getValue());

                        map.put(column.getName(), column.getValue());
                    }
                    mapList.add(map);
                }
                operation = "删除";
                break;
            default:
                break;
        }

        // 循环处理数据
        for (Map<String, String> map : mapList) {
            log.info("---------操作:[{}],数据=[{}]----------", operation, map);
            // 转成SQL
            String sql = sqlBuilder(tableName, map, operation);

            log.info("---------SQL:[{}]----------", sql);

            try{
                leoTest1Service.executeSql(operation, sql);
            }catch (Exception e){
                log.error("---------SQL执行异常:[{}]----------", e);
            }
        }

    }

    private String sqlBuilder(String tableName, Map<String, String> map, String operation) {
        StringBuilder sql = new StringBuilder();
        if ("添加".equals(operation)){
            sql.append("INSERT INTO ");
            sql.append(tableName);
            sql.append("(");
            for (String key : map.keySet()) {
                sql.append(key);
                sql.append(",");
            }
            sql.deleteCharAt(sql.length() - 1);
            sql.append(") VALUES (");
            for (String value : map.values()) {
                // 判断类型
                sql.append("'");
                sql.append(transformData(value));
                sql.append("',");
            }
            sql.deleteCharAt(sql.length() - 1);
            sql.append(")");
        } else if ("更新".equals(operation)){
            sql.append("UPDATE ");
            sql.append(tableName);
            sql.append(" SET ");
            for (String key : map.keySet()) {
                if ("id".equals(key)){
                    continue;
                }
                // 如果value是空，不更新
                if (null == map.get(key) || "".equals(map.get(key))){
                    continue;
                }
                sql.append(key);
                sql.append("=");
                sql.append("'");
                sql.append(transformData(map.get(key)));
                sql.append("'");
                sql.append(",");
            }
            sql.deleteCharAt(sql.length() - 1);
            sql.append(" WHERE ");
            sql.append("id=");
            sql.append(map.get("id"));
        } else if ("删除".equals(operation)){
            sql.append("DELETE FROM ");
            sql.append(tableName);
            sql.append(" WHERE ");
            sql.append("id=");
            sql.append(map.get("id"));
        }

        return sql.toString();
    }

    private Object transformData(String value) {
        Object obj = value;
        return obj;
    }

    /**
     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空，则返回空字符串。</br>
     * 例如：HELLO_WORLD->HelloWorld
     *
     * @param name 转换前的下划线大写方式命名的字符串
     * @return 转换后的驼峰式命名的字符串
     */
    public static String camelName(String name) {
        StringBuilder result = new StringBuilder();
        // 快速检查
        if (name == null || name.isEmpty()) {
            // 没必要转换
            return "";
        } else if (!name.contains("_")) {
            // 不含下划线，仅将首字母小写
            return name.substring(0, 1).toLowerCase() + name.substring(1);
        }
        // 用下划线将原始字符串分割
        String camels[] = name.split("_");
        for (String camel : camels) {
            // 跳过原始字符串中开头、结尾的下换线或双重下划线
            if (camel.isEmpty()) {
                continue;
            }
            // 处理真正的驼峰片段
            if (result.length() == 0) {
                // 第一个驼峰片段，全部字母都小写
                result.append(camel.toLowerCase());
            } else {
                // 其他的驼峰片段，首字母大写
                result.append(camel.substring(0, 1).toUpperCase());
                result.append(camel.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }
}